package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.enums.PaymentStatusEnum;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.order.mapper.OrderInfoMapper;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentInfoService;
import com.atguigu.yygh.order.service.WxPayService;
import com.atguigu.yygh.order.utils.HttpRequestHelper;
import com.atguigu.yygh.patient.client.PatientFeignClient;
import com.atguigu.yygh.rabbit.constaner.MqConst;
import com.atguigu.yygh.rabbit.service.MqService;
import com.atguigu.yygh.schedule.client.ScheduleFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderCountQueryVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.OrderQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2022-10-07
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private PatientFeignClient patientFeignClient;

    @Autowired
    private ScheduleFeignClient scheduleFeignClient;

    @Autowired
    private PaymentInfoService paymentInfoService;

    @Autowired
    private MqService mqService;

    @Autowired
    private WxPayService wxPayService;

    @Override
    public Long submitOrder(String scheduleId, Long patientId) {
        OrderInfo orderInfo = new OrderInfo();
        //排班信息
        ScheduleOrderVo scheduleOrderVo = scheduleFeignClient.getScheduleOrderVo(scheduleId);
        BeanUtils.copyProperties(scheduleOrderVo,orderInfo);
        orderInfo.setScheduleId(scheduleOrderVo.getHosScheduleId());

        //就诊信息
        Patient patient = patientFeignClient.getPatient(patientId);
        orderInfo.setUserId(patient.getUserId());
        orderInfo.setPatientId(patient.getId());
        orderInfo.setPatientName(patient.getName());
        orderInfo.setPatientPhone(patient.getPhone());

        //当前时间是否超过挂号截止时间
        if(new DateTime(scheduleOrderVo.getStopTime()).isBeforeNow()){
            throw new YyghException(20001,"预约挂号时间已经过了");
        }
        //发送信息去第三方医院,查看是否有号
            //如果没有号    返回错误信息
        HashMap<String, Object> requestMap = new HashMap<>();
        requestMap.put("hoscode",orderInfo.getHoscode());
        requestMap.put("depcode",orderInfo.getDepcode());
        requestMap.put("hosScheduleId",orderInfo.getScheduleId());
        requestMap.put("reserveDate",orderInfo.getReserveDate());
        requestMap.put("reserveTime",orderInfo.getReserveTime());
        requestMap.put("amount",orderInfo.getAmount());
        JSONObject jsonObject = HttpRequestHelper.sendRequest(requestMap, "http://localhost:9998/order/submitOrder");
        //有号    返回剩余号    设置订单交易号   订单状态 resultCode
        if(jsonObject != null && jsonObject.getInteger("code") == 200){
            //挂号成功
            JSONObject result = jsonObject.getJSONObject("data");
            orderInfo.setHosRecordId(result.getString("hosRecordId"));
            orderInfo.setNumber(result.getInteger("number"));
            orderInfo.setFetchTime(result.getString("fetchTime"));
            orderInfo.setFetchAddress(result.getString("fetchAddress"));
            orderInfo.setOutTradeNo(System.currentTimeMillis()+""+new Random().nextInt(1000));
            orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());
            //排班可预约数
            Integer reservedNumber = result.getInteger("reservedNumber");
            //剩余可预约数
            Integer availableNumber = result.getInteger("availableNumber");
            //保存订单信息
            baseMapper.insert(orderInfo);
            //更新剩余预约号
            OrderMqVo orderMqVo = new OrderMqVo();
            orderMqVo.setScheduleId(scheduleId);
            orderMqVo.setAvailableNumber(availableNumber);
            orderMqVo.setReservedNumber(reservedNumber);
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(orderInfo.getPatientPhone());
            String reserveDate =
                    new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd")
                            + (orderInfo.getReserveTime()==0 ? "上午": "下午");
            Map<String,Object> param = new HashMap<String,Object>(){{
                put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());
                put("amount", orderInfo.getAmount());
                put("reserveDate", reserveDate);
                put("name", orderInfo.getPatientName());
                put("quitTime", new DateTime(orderInfo.getQuitTime()).toString("yyyy-MM-dd HH:mm"));
            }};
            msmVo.setParam(param);
            orderMqVo.setMsmVo(msmVo);
            //发送到消息队列
            mqService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);
            //发送短信通知
            mqService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM,MqConst.ROUTING_MSM_ITEM,msmVo);
            return orderInfo.getId();
        }else {
            throw new YyghException(20001,"挂号失败");
        }
    }

    @Override
    public Page<OrderInfo> selectPage(Integer pageNum, Integer pageSize, OrderQueryVo queryVo) {
        Page<OrderInfo> page = new Page<>(pageNum,pageSize);
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        //医院名称
        queryWrapper.like(!StringUtils.isEmpty(queryVo.getKeyword()),"hosname",queryVo.getKeyword());
        //用户id
        queryWrapper.eq("user_id",queryVo.getUserId());
        //就诊人id
        queryWrapper.eq(queryVo.getPatientId() != null , "patient_id",queryVo.getPatientId());
        queryWrapper.eq(!StringUtils.isEmpty(queryVo.getOutTradeNo()),"out_trade_no",queryVo.getOutTradeNo());
        queryWrapper.like(!StringUtils.isEmpty(queryVo.getPatientName()),"patient_name",queryVo.getPatientName());
        queryWrapper.eq(!StringUtils.isEmpty(queryVo.getOrderStatus()),"order_status",queryVo.getOrderStatus());
        queryWrapper.eq(!StringUtils.isEmpty(queryVo.getReserveDate()),"reserveDate",queryVo.getReserveDate());
        queryWrapper.ge(!StringUtils.isEmpty(queryVo.getCreateTimeBegin()),"create_time",queryVo.getCreateTimeBegin());
        queryWrapper.le(!StringUtils.isEmpty(queryVo.getCreateTimeEnd()),"create_time",queryVo.getCreateTimeEnd());
        baseMapper.selectPage(page,queryWrapper);
        page.getRecords().stream().forEach(orderInfo->{
            orderInfo.getParam().put("orderStatusString",OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus()));
        });
        return page;
    }

    @Override
    public void updatePayStatus(Long orderId,Integer status) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(status);
        baseMapper.updateById(orderInfo);
    }

    @Override
    public void cancelOrder(Long orderId) throws Exception {
        //1 判断现在时间是否超过退款最后时间
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        if(new DateTime(orderInfo.getQuitTime()).isBeforeNow()){
            throw new YyghException(20001,"取消预约失败,现在超过取消时间!");
        }
        //2 查看第三方医院是否可以退款
        HashMap<String, Object> map = new HashMap<>();
        map.put("hoscode",orderInfo.getHoscode());
        map.put("hosRecordId",orderInfo.getHosRecordId());
        JSONObject response = HttpRequestHelper.sendRequest(map, "http://localhost:9998/order/updateCancelStatus");
        if (response == null || response.getIntValue("code") != 200){
            throw new YyghException(20001,"取消失败");
        }
        //3 判断是否付钱过
        if(orderInfo.getOrderStatus().equals(OrderStatusEnum.PAID.getStatus())){
            //是  微信   退款记录添加
           Boolean isRefund =  wxPayService.refund(orderId);
           if (!isRefund){
               throw new YyghException(20001,"退款记录添加异常!");
           }
        }
        //4 更新订单状态
        updatePayStatus(orderId,OrderStatusEnum.CANCLE.getStatus());
        // 修改 支付记录状态
        paymentInfoService.updateStatus(orderId,PaymentStatusEnum.REFUND.getStatus());
        // 医院排班 + 1
        OrderMqVo orderMqVo = new OrderMqVo();
        orderMqVo.setScheduleId(orderInfo.getHoscode()+":"+orderInfo.getDepcode()+":"+orderInfo.getScheduleId());
        mqService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);
        //5 给就诊人发送短信
        MsmVo msmVo = new MsmVo();
        msmVo.setPhone(orderInfo.getPatientPhone());
        msmVo.setTemplateCode("取消预约");
        String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "上午": "下午");
        Map<String,Object> param = new HashMap<String,Object>(){{
            put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());
            put("reserveDate", reserveDate);
            put("name", orderInfo.getPatientName());
        }};
        msmVo.setParam(param);
        mqService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM,MqConst.ROUTING_MSM_ITEM,msmVo);
    }

    @Override
    public void sendMessage() {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reserve_date",new DateTime().toString("yyyy-MM-dd"));
        queryWrapper.ne("order_status",OrderStatusEnum.CANCLE.getStatus());
        List<OrderInfo> list = baseMapper.selectList(queryWrapper);
        for (OrderInfo orderInfo : list) {
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(orderInfo.getPatientPhone());
            msmVo.setTemplateCode("预约提醒");
            String reserveDate = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd") + (orderInfo.getReserveTime()==0 ? "上午": "下午");
            Map<String,Object> param = new HashMap<String,Object>(){{
                put("title", orderInfo.getHosname()+"|"+orderInfo.getDepname()+"|"+orderInfo.getTitle());
                put("reserveDate", reserveDate);
                put("name", orderInfo.getPatientName());
            }};
            msmVo.setParam(param);
            mqService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM,MqConst.ROUTING_MSM_ITEM,msmVo);
        }
    }

    @Override
    //reserveDate
    public Map<String, Object> getOrderCountList(OrderCountQueryVo orderCountQueryVo) {

        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("reserve_date");
        queryWrapper.like(!StringUtils.isEmpty(orderCountQueryVo.getHosname()),"hosname",orderCountQueryVo.getHosname());
        queryWrapper.ge(!StringUtils.isEmpty(orderCountQueryVo.getReserveDateBegin()),"reserve_date",orderCountQueryVo.getReserveDateBegin());
        queryWrapper.le(!StringUtils.isEmpty(orderCountQueryVo.getReserveDateEnd()),"reserve_date",orderCountQueryVo.getReserveDateEnd());
        queryWrapper.groupBy("reserve_date");
        queryWrapper.orderByAsc("reserve_date");
        List<Object> dateList = baseMapper.selectObjs(queryWrapper);
        List<Integer> countList = new ArrayList<>();
        for (Object o : dateList) {
            QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
            wrapper.like(!StringUtils.isEmpty(orderCountQueryVo.getHosname()),"hosname",orderCountQueryVo.getHosname());
            wrapper.eq("reserve_date",o);
            countList.add(baseMapper.selectCount(wrapper));
        }
        Map<String, Object> map = new HashMap<>();
        map.put("dateList",dateList);
        map.put("countList",countList);
        return map;
    }
}
